home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / DEMOS / YACME / Editor.c next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  30.1 KB  |  1,373 lines

  1. /*===========================================================================*
  2.  *
  3.  *                YACME
  4.  *            Yet Another ColorMap Editor
  5.  *
  6.  *            Patrick BOUCHAUD - 1993
  7.  *                          SGI Switzerland
  8.  *
  9.  *                    Converted to OpenGL using GLUT
  10.  *
  11.  *===========================================================================*/
  12.  
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <math.h>
  17. #include <GL/glut.h>
  18.  
  19. #include "mallocbis.h"
  20.  
  21. /* For portability... */
  22. #undef fsqrt
  23. #define fsqrt(_a)     sqrt(_a)
  24.  
  25. #define    SUP(a,b)    ( ((a)>(b)) ? (a) : (b) )
  26. #define    INF(a,b)    ( ((a)<(b)) ? (a) : (b) )
  27. #define    ABS(a)        ( ((a)<0) ? -(a) : (a) )
  28. #define    POINT        1
  29. #define    CURVE        2
  30. #define    LEFT_TAN    3
  31. #define    RIGHT_TAN    4
  32. #define    MANUAL        1
  33. #define    CONTINUOUS    2
  34.  
  35. #define    CONSTANT    1
  36. #define    LINEAR        2
  37. #define    POLYNOMIAL    3
  38.  
  39. #define    TabCmpnt(c,n)    TabCmpnt[(n)*4+(c)]
  40.  
  41. #define    MAXNDX    (dimlut-1)
  42.  
  43. #define    WINHEIGHT    381
  44. #define    WINWIDTH    318
  45.  
  46. #define LUTRATIO    ((float)MAXNDX/255.)
  47.  
  48. #define    LEFT        LUTRATIO*(-5.)
  49. #define    RIGHT        LUTRATIO*(260.)
  50. #define    BOTTOM        LUTRATIO*(-5.)
  51. #define    TOP            LUTRATIO*(315.)
  52. #define    TANLEN        LUTRATIO*(25.)
  53.  
  54. typedef float Matrix[4][4];
  55.  
  56. typedef struct    {
  57.     float    x0, y0,
  58.         x1, y1;
  59. } Tangente;
  60.  
  61. typedef struct UserPointStruct    {
  62.  
  63.     float        x, y;
  64.     Tangente    tg;
  65.     int            mode;
  66.     float        polynome[4];
  67.     struct        UserPointStruct *next, *last;
  68.  
  69. } UserPoint;
  70.  
  71. void ResetCMap(void);
  72. void ApplyCMap(void);
  73. void YACME_makeMenu(void);
  74. extern void invertmat(float from[4][4], float to[4][4]);
  75.  
  76. static UserPoint *FreePointList = NULL;
  77. #define    newPoint( point ) newItem( point, FreePointList, UserPoint )
  78. #define    freePoint( point ) freeItem( point, FreePointList )
  79.  
  80. typedef struct    {
  81.     int    type,
  82.         cmpnt,
  83.         ndx;
  84.  
  85.     UserPoint *upoint;
  86. } PickObject;
  87.  
  88. struct {
  89.     int leftdown, middledown, rightdown;
  90. } mouse;
  91.  
  92. void YACME_pick( int mx, int my, PickObject *obj );
  93. void YACME_update( int cmpnt, UserPoint *upoint );
  94. int    YACME_get( unsigned long *table );
  95.  
  96. void    DeletePoint( int cmpnt, UserPoint *upoint );
  97. int    MovePoint( int, int );
  98. int    MoveTangente( int, int, int );
  99. int    InsertPoint( PickObject *obj );
  100.  
  101. void    GetPolynome( int mode,
  102.         float a0, float b0, float t0,
  103.         float a1, float b1, float t1,
  104.         float coeff[4] );
  105. void    OrthoTransform( int mx, int my, float *x, float *y );
  106. float    Polynome4( float x, float *polynome );
  107.  
  108. static int    DrawCurve[4] = { 1, 1, 1, 1, },
  109.         modifiedCurve[4] = { 1, 1, 1, 1 },
  110.         YACME_refresh = MANUAL,
  111.         curCmpnt = 0, curType = 0,
  112.         Mousex, Mousey;
  113.  
  114. static float *TabCmpnt;
  115. static int    YACME_switch_menu = 0,
  116.     YACME_mode_menu, YACME_edit_menu;
  117. static int YACME_win = 0, W, H , update = 0;
  118. static UserPoint *userPoint[4], *userPointSvg[4], *curPoint = NULL;
  119.  
  120. static void Redraw( void );
  121. static void Reshape( int, int );
  122. static void Mouse( int, int, int, int );
  123. static void Motion( int, int );
  124. static void Key( unsigned char, int, int );
  125. static void Special( int, int, int );
  126. static void YACME_menuFunc( int );
  127.  
  128. typedef void (*CallBack)(void);
  129. static CallBack newmapCB, applyCB;
  130. static int dimlut;
  131.  
  132. /*---------------------------------------------------------------------------*
  133.  *            YACME_init
  134.  *---------------------------------------------------------------------------*/
  135. void
  136. YACME_init(
  137.     int x, int y, int w, int h,
  138.     int dim, float **list,
  139.     CallBack newmapFunc, CallBack applyFunc)
  140. {
  141.     int    i, j;
  142.     UserPoint *userpoint;
  143.  
  144.     if (YACME_win) return;
  145.  
  146.     dimlut = dim;
  147.     newmapCB = newmapFunc;
  148.     applyCB = applyFunc;
  149.  
  150.     if (*list==NULL)
  151.     {
  152.         *list = TabCmpnt = (float *) malloc( 4*dimlut*sizeof(float) );
  153.         for (i=0; i<4; i++)
  154.         {
  155.             newPoint( userPoint[i] );
  156.             userpoint = userPoint[i];
  157.             userpoint->mode = POLYNOMIAL;
  158.             userpoint->x = 0.;
  159.             userpoint->y = 0.;
  160.             userpoint->last    = NULL;
  161.             userpoint->tg.x0 = 0.;
  162.             userpoint->tg.y0 = 0.;
  163.             userpoint->tg.x1 = TANLEN;
  164.             userpoint->tg.y1 = 0.;
  165.     
  166.             newPoint( userpoint->next );
  167.             userpoint = userpoint->next;
  168.             userpoint->mode = POLYNOMIAL;
  169.             userpoint->x = (float)MAXNDX;
  170.             userpoint->y = (float)MAXNDX;
  171.             userpoint->last    = userPoint[i];
  172.             userpoint->next    = NULL;
  173.             userpoint->tg.x0 = (float)(MAXNDX-TANLEN);
  174.             userpoint->tg.y0 = (float)MAXNDX;
  175.             userpoint->tg.x1 = (float)MAXNDX;
  176.             userpoint->tg.y1 = (float)MAXNDX;
  177.         }
  178.     }
  179.     else
  180.     {
  181.         UserPoint *upoint[4], *lastupoint[4]={0,0,0,0};
  182.  
  183.         TabCmpnt = *list;
  184.         for (i=0; i<dim; i++)
  185.         {
  186.             for (j=0; j<4; j++)
  187.             {
  188.                 if (i==0)
  189.                 {
  190.                     newPoint( userPoint[j] );
  191.                     upoint[j] = userPoint[j];
  192.                 }
  193.                 else
  194.                 {
  195.                     newPoint( upoint[j]->next );
  196.                     upoint[j] = upoint[j]->next;
  197.                 }
  198.                 upoint[j]->next = NULL;
  199.                 upoint[j]->last = lastupoint[j];
  200.                 upoint[j]->mode = LINEAR;
  201.                 upoint[j]->x = (float)i;
  202.                 upoint[j]->y = (float)MAXNDX*TabCmpnt(j,i);
  203.                 if (i==0)
  204.                 {
  205.                     upoint[j]->tg.x0 = 0.;
  206.                     upoint[j]->tg.y0 = 0.;
  207.                     upoint[j]->tg.x1 = TANLEN;
  208.                     upoint[j]->tg.y1 = 0.;
  209.                 }
  210.                 else
  211.                 {
  212.                     float    slope = upoint[j]->y - upoint[j]->last->y,
  213.                             dx = TANLEN/fsqrt(slope*slope + 1),
  214.                             dy = slope*dx;
  215.                     upoint[j]->tg.x0 = upoint[j]->x - dx;
  216.                     upoint[j]->tg.y0 = upoint[j]->y - dy;
  217.                     upoint[j]->tg.x1 = upoint[j]->x + dx;
  218.                     upoint[j]->tg.y1 = upoint[j]->y + dy;
  219.                 }
  220.  
  221.                 lastupoint[j] = upoint[j];
  222.             }
  223.         }
  224.     }
  225.  
  226. /*
  227.     TabComponents update
  228.     --------------------
  229. */
  230.     for (i=0; i<4; i++)
  231.     {
  232.         for (userpoint=userPoint[i]; userpoint!=NULL; userpoint=userpoint->next)
  233.             YACME_update( i, userpoint );
  234.     }
  235.     ApplyCMap();
  236.  
  237.     if (!YACME_win)
  238.     {
  239.         glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
  240.         glutInitWindowPosition( x, y );
  241.         glutInitWindowSize( w, h );
  242.         YACME_win = glutCreateWindow( "LUT editor" );
  243.         glutDisplayFunc( Redraw );
  244.         glutReshapeFunc( Reshape );
  245.         glutMouseFunc( Mouse );
  246.         glutMotionFunc( Motion );
  247.         glutPassiveMotionFunc( Motion );
  248.         glutSpecialFunc( Special );
  249.         glutKeyboardFunc( Key );
  250.         
  251.         glMatrixMode( GL_PROJECTION );
  252.         glLoadIdentity();
  253.         glOrtho( LEFT, RIGHT, BOTTOM, TOP, -1., 1. );
  254.  
  255.         glClearColor( 0.66, 0.66, 0.66, 1. );
  256.         glClear( GL_COLOR_BUFFER_BIT );
  257.         glShadeModel( GL_FLAT );
  258.         glutSwapBuffers();
  259.  
  260.         YACME_makeMenu();
  261.     }
  262. }
  263.  
  264. /*---------------------------------------------------------------------------*
  265.  *    Key
  266.  *---------------------------------------------------------------------------*/
  267. /* ARGSUSED1 */
  268. static void
  269. Key( unsigned char key, int x, int y )
  270. {
  271.     UserPoint *previousPoint;
  272.     switch (key)
  273.     {
  274.         case 27:    /* Escape */
  275.             exit(0);
  276.             break;
  277.  
  278.         case 127:    /* BackSpace */
  279.         case 8:        /* Delete */
  280.             if (!curPoint) return;
  281.             previousPoint = (curPoint->last ? curPoint->last : userPoint[curCmpnt]);
  282.             DeletePoint( curCmpnt, curPoint );
  283.             modifiedCurve[curCmpnt] = 1;
  284.             update = 1;
  285.             curPoint = previousPoint;
  286.             break;
  287.     }
  288.     glutPostRedisplay();
  289. }
  290.  
  291. /*---------------------------------------------------------------------------*
  292.  *      Special
  293.  *---------------------------------------------------------------------------*/
  294. /* ARGSUSED1 */
  295. static void
  296. Special( int key, int xx, int yy )
  297. {
  298.     int x, y, minx, maxx;
  299.     float dx, dy;
  300.     if (curPoint == NULL ) return;
  301.     if (curPoint->next == NULL) return;
  302.     if (curPoint->last == NULL) return;
  303.  
  304.     x = (int)curPoint->x;
  305.     y = (int)curPoint->y;
  306.  
  307.     minx = (int)curPoint->last->x; minx++;
  308.     maxx = (int)curPoint->next->x; maxx--;
  309.  
  310.     switch (key)
  311.     {
  312.         case GLUT_KEY_LEFT:
  313.             if (x > minx) x--;
  314.             break;
  315.  
  316.         case GLUT_KEY_RIGHT:
  317.             if (x < maxx) x++;
  318.             break;
  319.  
  320.         case GLUT_KEY_UP:
  321.             if (y < MAXNDX) y++;
  322.             break;
  323.  
  324.         case GLUT_KEY_DOWN:
  325.             if (y > 0) y--;
  326.             break;
  327.     }
  328.  
  329.     dx = (float)x - curPoint->x;
  330.     curPoint->x += dx;
  331.     curPoint->tg.x0 += dx;
  332.     curPoint->tg.x1 += dx;
  333.  
  334.     dy = (float)y - curPoint->y;
  335.     curPoint->y = y;
  336.     curPoint->tg.y0 += dy;
  337.     curPoint->tg.y1 += dy;
  338.  
  339.     update = 1;
  340.     glutPostRedisplay();
  341. }
  342.  
  343. /*---------------------------------------------------------------------------*
  344.  *    Reshape
  345.  *---------------------------------------------------------------------------*/
  346. static void
  347. Reshape( int w, int h )
  348. {
  349.     glViewport( 0, 0, w, h );
  350.     W = w;
  351.     H = h;
  352.     glutPostRedisplay();
  353. }
  354.  
  355. /*---------------------------------------------------------------------------*
  356.  *    Mouse
  357.  *---------------------------------------------------------------------------*/
  358. static void
  359. Mouse( int button, int state, int x, int y )
  360. {
  361.     PickObject    object;
  362.  
  363.     y = H-y;
  364.     switch (button)
  365.     {
  366.         case GLUT_RIGHT_BUTTON:
  367.             mouse.rightdown = (state==GLUT_DOWN);
  368.             break;
  369.  
  370.         case GLUT_MIDDLE_BUTTON:
  371.             mouse.middledown = (state==GLUT_DOWN);
  372.             break;
  373.  
  374.         case GLUT_LEFT_BUTTON:
  375.             mouse.leftdown = (state==GLUT_DOWN);
  376.             if (mouse.leftdown)
  377.             {
  378.                 YACME_pick( x, y, &object );
  379.                 curType = object.type;
  380.                 switch ( object.type )
  381.                 {
  382.                     case CURVE:
  383.                         if ((curType = InsertPoint( &object ) != 0))
  384.                         {
  385.                             curPoint = object.upoint;
  386.                             curCmpnt = object.cmpnt;
  387.                         }
  388.                         else curPoint = NULL;
  389.                         break;
  390.  
  391.                     case POINT:
  392.                     case LEFT_TAN:
  393.                     case RIGHT_TAN:
  394.                         curPoint = object.upoint;
  395.                         curCmpnt = object.cmpnt;
  396.                         break;
  397.  
  398.                     default:
  399.                         curPoint = NULL;
  400.             }
  401.             break;
  402.         }
  403.     }
  404.     glutPostRedisplay();
  405. }
  406.  
  407. /*---------------------------------------------------------------------------*
  408.  *    Motion
  409.  *---------------------------------------------------------------------------*/
  410. static void
  411. Motion( int x, int y )
  412. {
  413.     Mousex = x;
  414.     Mousey = H-y;
  415.     if (mouse.leftdown)
  416.     {
  417.         switch (curType)
  418.         {
  419.             case POINT:
  420.                 update = MovePoint( Mousex, Mousey );
  421.                 break;
  422.  
  423.             case LEFT_TAN:
  424.                 update = MoveTangente( -1, Mousex, Mousey );
  425.                 break;
  426.  
  427.             case RIGHT_TAN:
  428.                 update = MoveTangente( 1, Mousex, Mousey );
  429.                 break;
  430.         }
  431.     }
  432.     glutPostRedisplay();
  433. }
  434.  
  435. /*---------------------------------------------------------------------------*
  436.  *            YACME_makeMenu
  437.  *---------------------------------------------------------------------------*/
  438.  
  439. #define    CONTINUOUS_ITEM    5
  440. #define    MANUAL_ITEM        4
  441. #define    APPLY_ITEM        3
  442. #define    RESET_ITEM        2
  443. #define    CLOSE_ITEM        1
  444.  
  445. #define    RED_ITEM    10
  446. #define    GREEN_ITEM    11
  447. #define    BLUE_ITEM    12
  448. #define    ALPHA_ITEM    13
  449.  
  450. #define    CONSTANT_ITEM    22
  451. #define    LINEAR_ITEM        21
  452. #define    POLYNOM_ITEM    20
  453.  
  454. #define    EDIT_RED_ITEM    30
  455. #define    EDIT_GREEN_ITEM    31
  456. #define    EDIT_BLUE_ITEM    32
  457. #define    EDIT_ALPHA_ITEM    33
  458.  
  459. void
  460. YACME_makeMenu(void)
  461. {
  462.     YACME_edit_menu = glutCreateMenu( YACME_menuFunc );
  463.     glutAddMenuEntry( "red", EDIT_RED_ITEM );
  464.     glutAddMenuEntry( "green", EDIT_GREEN_ITEM );
  465.     glutAddMenuEntry( "blue", EDIT_BLUE_ITEM );
  466.     glutAddMenuEntry( "alpha", EDIT_ALPHA_ITEM );
  467.  
  468.     YACME_mode_menu = glutCreateMenu( YACME_menuFunc );
  469.     glutAddMenuEntry( "Constant  ", CONSTANT_ITEM );
  470.     glutAddMenuEntry( "Linear    ", LINEAR_ITEM );
  471.     glutAddMenuEntry( "Polynomial", POLYNOM_ITEM );
  472.  
  473.     YACME_switch_menu = glutCreateMenu( YACME_menuFunc );
  474.     glutAddMenuEntry( "Red    on", RED_ITEM );
  475.     glutAddMenuEntry( "Green on", GREEN_ITEM );
  476.     glutAddMenuEntry( "Blue   on", BLUE_ITEM );
  477.     glutAddMenuEntry( "Alpha on", ALPHA_ITEM );
  478.  
  479.     glutCreateMenu( YACME_menuFunc );
  480.     glutAddMenuEntry( "Manual    ", MANUAL_ITEM );
  481.     glutAddMenuEntry( "Apply", APPLY_ITEM );
  482.     glutAddMenuEntry( "Reset", RESET_ITEM );
  483.     glutAddMenuEntry( "Close", CLOSE_ITEM );
  484.     glutAddSubMenu(   "Mode... ", YACME_mode_menu );
  485.     glutAddSubMenu(   "Switch... ", YACME_switch_menu );
  486.     glutAddSubMenu(   "Edit... ", YACME_edit_menu );
  487.  
  488.     glutAttachMenu( GLUT_RIGHT_BUTTON );
  489. }
  490.  
  491. /*---------------------------------------------------------------------------*
  492.  *    YACME_menuFunc
  493.  *---------------------------------------------------------------------------*/
  494. static void
  495. YACME_menuFunc( int item )
  496. {
  497.     switch( item )
  498.     {
  499.         case CLOSE_ITEM:
  500.             break;
  501.  
  502.         case RESET_ITEM:
  503.             if (applyCB) (*applyCB)();
  504.             else if (newmapCB) (*newmapCB)();
  505.             ResetCMap();
  506.             curPoint = NULL;
  507.             break;
  508.  
  509.         case APPLY_ITEM:
  510.             if (applyCB) (*applyCB)();
  511.             else if (newmapCB) (*newmapCB)();
  512.             ApplyCMap();
  513.             break;
  514.  
  515.         case MANUAL_ITEM:    /* switch to continuous */
  516.             glutChangeToMenuEntry( 1, "Continuous", CONTINUOUS_ITEM );
  517.             YACME_refresh = CONTINUOUS;
  518.             break;
  519.  
  520.         case CONTINUOUS_ITEM: /* switch to manual */
  521.             glutChangeToMenuEntry( 1, "Manual    ", MANUAL_ITEM );
  522.             if (newmapCB) (*newmapCB)();
  523.             ApplyCMap();
  524.             YACME_refresh = MANUAL;
  525.             break;
  526.  
  527.         case RED_ITEM:
  528.             DrawCurve[0] = !DrawCurve[0];
  529.             if (DrawCurve[0])
  530.                 glutChangeToMenuEntry( 1, "Red     on", RED_ITEM );
  531.             else
  532.                 glutChangeToMenuEntry( 1, "Red    off", RED_ITEM );
  533.             curPoint = NULL;
  534.             break;
  535.  
  536.         case GREEN_ITEM:
  537.             DrawCurve[1] = !DrawCurve[1];
  538.             if (DrawCurve[1])
  539.                 glutChangeToMenuEntry( 2, "Green on", GREEN_ITEM );
  540.             else
  541.                 glutChangeToMenuEntry( 2, "Green off", GREEN_ITEM );
  542.             curPoint = NULL;
  543.             break;
  544.  
  545.         case BLUE_ITEM:
  546.             DrawCurve[2] = !DrawCurve[2];
  547.             if (DrawCurve[2])
  548.                 glutChangeToMenuEntry( 3, "Blue   on", BLUE_ITEM );
  549.             else
  550.                 glutChangeToMenuEntry( 3, "Blue   off", BLUE_ITEM );
  551.             curPoint = NULL;
  552.             break;
  553.  
  554.         case ALPHA_ITEM:
  555.             DrawCurve[3] = !DrawCurve[3];
  556.             if (DrawCurve[3])
  557.                 glutChangeToMenuEntry( 4, "Alpha on", ALPHA_ITEM );
  558.             else
  559.                 glutChangeToMenuEntry( 4, "Alpha off", ALPHA_ITEM );
  560.             curPoint = NULL;
  561.             break;
  562.  
  563.         case CONSTANT_ITEM:
  564.             if (curPoint != NULL)
  565.             {
  566.                 update = 1;
  567.                 curPoint->mode = CONSTANT;
  568.             }
  569.             break;
  570.  
  571.         case LINEAR_ITEM:
  572.             if (curPoint != NULL)
  573.             {
  574.                 update = 1;
  575.                 curPoint->mode = LINEAR;
  576.             }
  577.             break;
  578.  
  579.         case POLYNOM_ITEM:
  580.             if (curPoint != NULL)
  581.             {
  582.                 update = 1;
  583.                 curPoint->mode = POLYNOMIAL;
  584.             }
  585.             break;
  586.  
  587.         case EDIT_RED_ITEM:
  588.         case EDIT_GREEN_ITEM:
  589.         case EDIT_BLUE_ITEM:
  590.         case EDIT_ALPHA_ITEM:
  591.             curCmpnt = item-30;
  592.             curPoint = userPoint[curCmpnt];
  593.             break;
  594.     }
  595.     glutPostRedisplay();
  596. }
  597.  
  598. /*---------------------------------------------------------------------------*
  599.  *    output
  600.  *---------------------------------------------------------------------------*/
  601. static void
  602. output( float x, float y, char *string )
  603. {
  604.     int len, i;
  605.  
  606.     glRasterPos2f(x, y);
  607.     len = (int) strlen(string);
  608.     for (i = 0; i < len; i++)
  609.     {
  610.         glutBitmapCharacter(GLUT_BITMAP_8_BY_13, string[i]);
  611.     }
  612. }
  613.  
  614. /*---------------------------------------------------------------------------*
  615.  *    Redraw
  616.  *---------------------------------------------------------------------------*/
  617. static void
  618. Redraw( void )
  619. {
  620.     int    i, j, ndx, cmpnt, priority[4];
  621.     Tangente *tg;
  622.     UserPoint *upoint;
  623.     char string[256];
  624.  
  625.     if (update)
  626.     {
  627.         modifiedCurve[curCmpnt] = 1;
  628.         YACME_update( curCmpnt, curPoint );
  629.         if ( newmapCB && (YACME_refresh == CONTINUOUS))
  630.             (*newmapCB)();
  631.         update = 0;
  632.     }
  633.  
  634.     glClear( GL_COLOR_BUFFER_BIT );
  635.  
  636. /*
  637.     Barettes representant la table des couleurs
  638.     -------------------------------------------
  639. */
  640.     glBegin( GL_TRIANGLE_STRIP );
  641.         glColor3f(TabCmpnt(0,0), TabCmpnt(1,0), TabCmpnt(2,0));
  642.         glVertex2f( 0., 270.*LUTRATIO );
  643.         glVertex2f( 0., 310.*LUTRATIO );
  644.         glVertex2f( .5, 270.*LUTRATIO );
  645.         glVertex2f( .5, 310.*LUTRATIO );
  646.     glEnd();
  647.     for ( i=1; i<MAXNDX; i++ )
  648.     {
  649.         float x=(float)i - .5;
  650.         glBegin( GL_TRIANGLE_STRIP );
  651.             glColor3f(TabCmpnt(0,i), TabCmpnt(1,i), TabCmpnt(2,i));
  652.             glVertex2f( x, 270.*LUTRATIO );
  653.               glVertex2f( x, 310.*LUTRATIO );
  654.             glVertex2f( x+1., 270.*LUTRATIO );
  655.             glVertex2f( x+1., 310.*LUTRATIO );
  656.         glEnd();
  657.      }
  658.     glBegin( GL_TRIANGLE_STRIP );
  659.         glColor3f(TabCmpnt(0,MAXNDX), TabCmpnt(1,MAXNDX), TabCmpnt(2,MAXNDX));
  660.         glVertex2f( (float)MAXNDX-.5, 270.*LUTRATIO );
  661.         glVertex2f( (float)MAXNDX-.5, 310.*LUTRATIO );
  662.         glVertex2f( (float)MAXNDX, 270.*LUTRATIO );
  663.         glVertex2f( (float)MAXNDX, 310.*LUTRATIO );
  664.     glEnd();
  665.  
  666. /*
  667.     Graphe y = cpste(x)
  668.     -------------------
  669. */ 
  670.     glColor3f(0.,0.,0.);
  671.     glBegin( GL_TRIANGLE_STRIP );
  672.         glVertex2f( 0., 0. );
  673.         glVertex2f( (float) MAXNDX, 0. );
  674.         glVertex2f( 0., (float) MAXNDX );
  675.         glVertex2f( (float) MAXNDX, (float) MAXNDX );
  676.     glEnd();
  677.  
  678. /*
  679.     Curves y = cpste(x)
  680.     --------------------
  681. */
  682.     for ( i=0; i<curCmpnt; i++)
  683.     {
  684.         priority[i] = i;
  685.     }
  686.     for ( i=curCmpnt+1; i<4; i++ ) {
  687.         priority[i-1] = i;
  688.     }
  689.     priority[3] = curCmpnt;
  690.  
  691.     cmpnt = priority[0];
  692.     for ( i=0; i<4; i++, cmpnt=priority[i] ) if ( DrawCurve[cmpnt] )
  693.     {
  694.  
  695.         switch (cmpnt)
  696.         {
  697.             case 3: glColor3f(1.,1.,1.); break;
  698.             case 2: glColor3f(0.,0.,1.); break;
  699.             case 1: glColor3f(0.,1.,0.); break;
  700.             case 0: glColor3f(1.,0.,0.); break;
  701.         }
  702.  
  703.         for ( j=0; j<MAXNDX; j++ )
  704.         {
  705.             glBegin( GL_LINES );
  706.                 glVertex2f( (float)j, (float)MAXNDX*TabCmpnt(cmpnt,j) );
  707.                 glVertex2f( (float)(j+1), (float)MAXNDX*TabCmpnt(cmpnt,j+1) );
  708.             glEnd();
  709.         }
  710.     }
  711.  
  712.     if ( curPoint != NULL )
  713.     {
  714.         float h;
  715. /*
  716.         user defined points
  717.         -------------------
  718. */
  719.         upoint = userPoint[curCmpnt];
  720.         do {
  721. /*
  722.             Point
  723.             -----
  724. */
  725. #define    DIMPOINT (2.*LUTRATIO)
  726.  
  727.             glBegin( GL_TRIANGLE_STRIP );
  728.                 glVertex2f( upoint->x-DIMPOINT, upoint->y-DIMPOINT );
  729.                 glVertex2f( upoint->x-DIMPOINT, upoint->y+DIMPOINT );
  730.                 glVertex2f( upoint->x+DIMPOINT, upoint->y-DIMPOINT );
  731.                 glVertex2f( upoint->x+DIMPOINT, upoint->y+DIMPOINT );
  732.             glEnd();
  733. /*
  734.             Tangente
  735.             --------
  736. */
  737.             tg = &upoint->tg;
  738.             if (upoint->last ? upoint->last->mode == POLYNOMIAL : 0)
  739.             {
  740.                 glBegin( GL_LINES );
  741.                     glVertex2f( tg->x0, tg->y0 );
  742.                     glVertex2f( upoint->x, upoint->y );
  743.                 glEnd();
  744.                 glBegin( GL_LINE_LOOP );
  745.                     glVertex2f( tg->x0-DIMPOINT, tg->y0-DIMPOINT );
  746.                     glVertex2f( tg->x0-DIMPOINT, tg->y0+DIMPOINT );
  747.                     glVertex2f( tg->x0+DIMPOINT, tg->y0+DIMPOINT );
  748.                     glVertex2f( tg->x0+DIMPOINT, tg->y0-DIMPOINT );
  749.                 glEnd();
  750.             }
  751.             if (upoint->mode == POLYNOMIAL)
  752.             {
  753.                 glBegin( GL_LINES );
  754.                     glVertex2f( upoint->x, upoint->y );
  755.                     glVertex2f( tg->x1, tg->y1 );
  756.                 glEnd();
  757.                 glBegin( GL_LINE_LOOP );
  758.                     glVertex2f( tg->x1-DIMPOINT, tg->y1-DIMPOINT );
  759.                     glVertex2f( tg->x1-DIMPOINT, tg->y1+DIMPOINT );
  760.                     glVertex2f( tg->x1+DIMPOINT, tg->y1+DIMPOINT );
  761.                     glVertex2f( tg->x1+DIMPOINT, tg->y1-DIMPOINT );
  762.                 glEnd();
  763.             }
  764.             
  765.         } while ( (upoint=upoint->next) != NULL );
  766.  
  767. /*
  768.         Highlight current point
  769.         -----------------------
  770. */
  771.         ndx = curPoint->x;
  772.         h = curPoint->y;
  773.         switch (curCmpnt)
  774.         {
  775.             case 3: glColor3f(1.,1.,1.); break;
  776.             case 2: glColor3f(0.,0.,1.); break;
  777.             case 1: glColor3f(0.,1.,0.); break;
  778.             case 0: glColor3f(1.,0.,0.); break;
  779.         }
  780.         glBegin( GL_LINE_LOOP );
  781.             glVertex2f( (float)ndx-2.*DIMPOINT, h-2.*DIMPOINT );
  782.             glVertex2f( (float)ndx-2.*DIMPOINT, h+2.*DIMPOINT );
  783.             glVertex2f( (float)ndx+2.*DIMPOINT, h+2.*DIMPOINT );
  784.             glVertex2f( (float)ndx+2.*DIMPOINT, h-2.*DIMPOINT );
  785.         glEnd();
  786.     }
  787.     else
  788.     {
  789.         float x, y;
  790.         OrthoTransform( Mousex, Mousey, &x, &y );
  791.         ndx = (int) SUP( INF(x,(float)MAXNDX), 0 );
  792.     }
  793.  
  794. /*
  795.     Coordinates text string
  796.     -----------------------
  797. */
  798.     glColor3f( 0., 0., 0. );
  799.     sprintf( string,
  800.         "%.5d: rgba %.3f %.3f %.3f %.3f",
  801.         ndx,
  802.         TabCmpnt(0,ndx),
  803.         TabCmpnt(1,ndx),
  804.         TabCmpnt(2,ndx),
  805.         TabCmpnt(3,ndx)
  806.     );
  807.     output( LUTRATIO, 257.*LUTRATIO, string );
  808.  
  809.     glutSwapBuffers();
  810. }
  811.  
  812. /*---------------------------------------------------------------------------*
  813.  *            YACME_pick
  814.  *---------------------------------------------------------------------------*/
  815. void
  816. YACME_pick( int mousex, int mousey, PickObject *obj )
  817. {
  818.  int    cmpnt, i, priority[4];
  819.  float    x, y, val;
  820.  Tangente *tg;
  821.  UserPoint *upoint;
  822.  float pickrad;
  823.  
  824.  obj->type = -1;
  825.  OrthoTransform( mousex, mousey, &x, &y );
  826.  
  827. /*
  828.  On travaille en priorite sur les objets definis par l'utilisateur
  829.  -----------------------------------------------------------------
  830. */
  831.  for ( i=0; i<curCmpnt; i++) {
  832.     priority[i] = i;
  833.  }
  834.  for ( i=curCmpnt+1; i<4; i++ ) {
  835.     priority[i-1] = i;
  836.  }
  837.  priority[3] = curCmpnt;
  838.  
  839.  pickrad = 3.*LUTRATIO;
  840.  cmpnt = priority[3];
  841.  for ( i=3; i>=0; i--, cmpnt=priority[i] ) if ( DrawCurve[cmpnt] ) {
  842.  
  843.     upoint = userPoint[cmpnt];
  844.     while ( upoint != NULL ) {
  845. /*
  846.         On cherche le POINT
  847. */
  848.         if ( ABS(y-upoint->y) < pickrad && ABS(x-upoint->x) < pickrad ) {
  849.             obj->upoint    = upoint;
  850.             obj->cmpnt    = cmpnt;
  851.             obj->type    = POINT;
  852.             return;
  853.         }
  854. /*
  855.         On cherche la demi-tangente GAUCHE
  856. */
  857.         tg = &upoint->tg;
  858.         if ( ABS(x-tg->x0) < pickrad && ABS(y-tg->y0) < pickrad ) {
  859.             obj->upoint    = upoint;
  860.             obj->cmpnt    = cmpnt;
  861.             obj->type    = LEFT_TAN;
  862.             return;
  863.         }
  864. /*
  865.         On cherche la demi-tangente DROITE
  866. */
  867.         if ( ABS(x-tg->x1) < pickrad && ABS(y-tg->y1) < pickrad ) {
  868.             obj->upoint    = upoint;
  869.             obj->cmpnt    = cmpnt;
  870.             obj->type    = RIGHT_TAN;
  871.             return;
  872.         }
  873.         upoint = upoint->next;
  874.     }
  875. /*
  876.     Puis on cherche les coordonnees sur la CURVE
  877.     (On considere la precision suffisante pour le picking suivant l'axe X)
  878.     Remarque : on ne sort pas en ce cas, car la priorite est sur les objets
  879.     utilisateurs.
  880. */
  881.     upoint = userPoint[cmpnt];
  882.     while ( upoint->next->x < x ) {
  883.         upoint = upoint->next;
  884.         if ( upoint->next == NULL ) return;
  885.     }
  886.  
  887.     val = INF( SUP( Polynome4(x,upoint->polynome), 0.), (float)MAXNDX );
  888.     if ( ABS(y-val) < pickrad ) {
  889.         obj->cmpnt    = cmpnt;
  890.         obj->ndx    = ((x-(int)x)<.5) ? (int)x : (int)x+1;
  891.         obj->type    = CURVE;
  892.         return;
  893.     }
  894.  
  895.  }
  896. }
  897.  
  898. /*---------------------------------------------------------------------------*
  899.  *            YACME_update
  900.  *---------------------------------------------------------------------------*/
  901. void
  902. YACME_update( int cmpnt, UserPoint *upoint )
  903. {
  904.  int    i;
  905.  float    val, t0, t1;
  906.  Tangente *tg;
  907.  
  908.  tg = &upoint->tg;
  909.  if ( tg->x1 != tg->x0 ) {
  910.     t0 = (tg->y1-tg->y0) / (tg->x1-tg->x0);
  911.  } else {
  912.     t0 = (tg->y1-tg->y0)*10000.;
  913.  }
  914.  
  915.  TabCmpnt(cmpnt,(int) upoint->x) = upoint->y/(float)MAXNDX;
  916.  if ( upoint->last != NULL ) {
  917.  
  918.     tg = &upoint->last->tg;
  919.     if ( tg->x1 != tg->x0 ) {
  920.         t1 = (tg->y1-tg->y0) / (tg->x1-tg->x0);
  921.     } else {
  922.         t1 = (tg->y1-tg->y0)*10000.;
  923.     }
  924.  
  925.     GetPolynome(
  926.         upoint->last->mode,
  927.         upoint->last->x,
  928.         upoint->last->y,
  929.         t1,
  930.         upoint->x,
  931.         upoint->y,
  932.         t0,
  933.         upoint->last->polynome
  934.     );
  935.  
  936.     for ( i=1+(int) upoint->last->x; i<(int) upoint->x; i++ ) {
  937.         val = Polynome4((float) i, upoint->last->polynome)/(float)MAXNDX;
  938.         TabCmpnt(cmpnt,i) = INF( SUP(val,0.), 1. );
  939.     }
  940.  }
  941.  
  942.  if ( upoint->next != NULL ) {
  943.  
  944.     tg = &upoint->next->tg;
  945.     if ( tg->x1 != tg->x0 ) {
  946.         t1 = (tg->y1-tg->y0) / (tg->x1-tg->x0);
  947.     } else {
  948.         t1 = (tg->y1-tg->y0)*10000.;
  949.     }
  950.  
  951.     GetPolynome(
  952.         upoint->mode,
  953.         upoint->x,
  954.         upoint->y,
  955.         t0,
  956.         upoint->next->x,
  957.         upoint->next->y,
  958.         t1,
  959.         upoint->polynome
  960.     );
  961.  
  962.     for ( i=1+(int) upoint->x; i<(int) upoint->next->x; i++ ) {
  963.         val = Polynome4( (float) i, upoint->polynome )/(float)MAXNDX;
  964.         TabCmpnt(cmpnt,i) = INF( SUP(val,0.), 1. );
  965.     }
  966.     TabCmpnt(cmpnt,(int) upoint->next->x) = upoint->next->y/(float)MAXNDX;
  967.  }
  968. }
  969.  
  970. /*---------------------------------------------------------------------------*
  971.  *            freePointList
  972.  *---------------------------------------------------------------------------*/
  973. static void
  974. freePointList( UserPoint *upoint )
  975. {
  976.     while (upoint != NULL)
  977.     {
  978.         UserPoint *unext = upoint->next;
  979.         freePoint( upoint );
  980.         upoint = unext;
  981.     }
  982. }
  983.  
  984. /*---------------------------------------------------------------------------*
  985.  *            clonePointList
  986.  *---------------------------------------------------------------------------*/
  987. static UserPoint *
  988. clonePointList( UserPoint *base )
  989. {
  990.     UserPoint *clone, *upoint;
  991.  
  992.     if (base == NULL) return NULL;
  993.  
  994.     newPoint( clone );
  995.     upoint = clone;
  996.  
  997.     memcpy( upoint, base, sizeof(UserPoint) );
  998.     upoint->last = NULL;
  999.     upoint->next = NULL;
  1000.  
  1001.     while (base->next != NULL)
  1002.     {
  1003.         base = base->next;
  1004.         newPoint( upoint->next );
  1005.         memcpy( upoint->next, base, sizeof(UserPoint) );
  1006.         upoint->next->last = upoint;
  1007.         upoint->next->next = NULL;
  1008.         upoint = upoint->next;
  1009.     }
  1010.  
  1011.     return clone;
  1012. }
  1013.  
  1014. /*---------------------------------------------------------------------------*
  1015.  *            ApplyCMap
  1016.  *---------------------------------------------------------------------------*/
  1017. void
  1018. ApplyCMap(void)
  1019. {
  1020.     int    i;
  1021.  
  1022.     for (i=0; i<4; i++) if ( modifiedCurve[i] )
  1023.     {
  1024.         freePointList( userPointSvg[i] );
  1025.         userPointSvg[i] = clonePointList( userPoint[i] );
  1026.         modifiedCurve[i] = 0;
  1027.     }
  1028. }
  1029.  
  1030. /*---------------------------------------------------------------------------*
  1031.  *            ResetCMap
  1032.  *---------------------------------------------------------------------------*/
  1033. void
  1034. ResetCMap(void)
  1035. {
  1036.     int    i;
  1037.     UserPoint *upoint;
  1038.  
  1039.     for (i=0; i<4; i++) if ( modifiedCurve[i] )
  1040.     {
  1041.         freePointList( userPoint[i] );
  1042.         userPoint[i] = clonePointList( userPointSvg[i] );
  1043.         modifiedCurve[i] = 0;
  1044.  
  1045.         for (upoint=userPoint[i]; upoint!=NULL; upoint=upoint->next )
  1046.             YACME_update( i, upoint );
  1047.     }
  1048. }
  1049.  
  1050. /*---------------------------------------------------------------------------*
  1051.  *            InsertPoint
  1052.  *---------------------------------------------------------------------------*/
  1053. int
  1054. InsertPoint( PickObject *obj )
  1055. {
  1056.  float    dx, dy, slope, coeff[4];
  1057.  int    i;
  1058.  Tangente *tg;
  1059.  UserPoint *upoint, *userpoint;
  1060.  
  1061.  upoint = userPoint[obj->cmpnt];
  1062.  while ( (int) upoint->next->x <= obj->ndx ) {
  1063.     upoint = upoint->next;
  1064.     if ( upoint->next == NULL ) return 0;
  1065.  }
  1066.  if ( (int) upoint->x == obj->ndx ) {
  1067.     obj->upoint = upoint;
  1068.     return POINT;
  1069.  }
  1070.  
  1071.  newPoint( userpoint );
  1072.  
  1073.  userpoint->x = (float) obj->ndx;
  1074.  userpoint->y = Polynome4( obj->ndx, upoint->polynome );
  1075.  userpoint->y = SUP( INF(userpoint->y, (float)MAXNDX), 0. );
  1076.  userpoint->mode = upoint->mode;
  1077.  for ( i=0; i<4; i++ ) {
  1078.     userpoint->polynome[i] = upoint->polynome[i];
  1079.  }
  1080.  userpoint->next = upoint->next;
  1081.  userpoint->last = upoint;
  1082.  upoint->next = userpoint;
  1083.  userpoint->next->last = userpoint;
  1084.  
  1085. /*
  1086.  calcul de slope = P'(index)
  1087.  ---------------------------
  1088. */
  1089.  
  1090.  if ( userpoint->y == (float)MAXNDX || userpoint->y == 0. ) {
  1091.     dx = 25.;
  1092.     dy = 0.;
  1093.  } else {
  1094.     coeff[0] = userpoint->polynome[0]*3.;
  1095.     coeff[1] = userpoint->polynome[1]*2.;
  1096.     coeff[2] = userpoint->polynome[2];
  1097.     slope = coeff[0];
  1098.     for (i=1; i<3; i++) {
  1099.         slope *= (float) obj->ndx;    
  1100.         slope += coeff[i];
  1101.     }
  1102. /*
  1103.     Rappel :
  1104.     cos( arctg(x) ) = 1/sqr( 1 + x^2 );
  1105.     sin( arctg(x) ) = |x|/sqr( 1 + x^2 );
  1106. */
  1107.     dx = 25. / fsqrt( slope*slope + 1. );
  1108.     dy = dx*slope;
  1109.  }
  1110.  dx *= LUTRATIO;
  1111.  dy *= LUTRATIO;
  1112.  
  1113.  tg = &userpoint->tg;
  1114.  tg->x0 = userpoint->x - dx;
  1115.  tg->x1 = userpoint->x + dx;
  1116.  tg->y0 = userpoint->y - dy;
  1117.  tg->y1 = userpoint->y + dy;
  1118.  
  1119.  obj->upoint = userpoint;
  1120.  return POINT;
  1121. }
  1122.  
  1123. /*---------------------------------------------------------------------------*
  1124.  *            DeletePoint
  1125.  *---------------------------------------------------------------------------*/
  1126. void
  1127. DeletePoint( int cmpnt, UserPoint *upoint )
  1128. {
  1129.     if ( upoint == NULL || upoint->last == NULL || upoint->next == NULL )
  1130.         return;
  1131.     upoint->last->next = upoint->next;
  1132.     upoint->next->last = upoint->last;
  1133.     YACME_update( cmpnt, upoint->last );
  1134.     freePoint( upoint );
  1135. }
  1136.  
  1137. /*---------------------------------------------------------------------------*
  1138.  *            MovePoint
  1139.  *---------------------------------------------------------------------------*/
  1140. int
  1141. MovePoint( int mousex, int mousey )
  1142. {
  1143.     float    x, y, dx, dy, minx, maxx;
  1144.  
  1145.     OrthoTransform( mousex, mousey, &x, &y );
  1146.  
  1147.     y = SUP( INF(y,(float)MAXNDX), 0. );
  1148.     x = ((x-(int)x)<.5) ? (float)(int)x : (float)(int)(x+1);
  1149.     y = ((y-(int)y)<.5) ? (float)(int)y : (float)(int)(y+1);
  1150.     if ( curPoint->next != NULL && curPoint->last!= NULL )
  1151.     {
  1152.         minx = curPoint->last->x + 1.;
  1153.         maxx = curPoint->next->x - 1.;
  1154.         x = SUP( INF(x, maxx), minx );
  1155.  
  1156.         dx = (float)x - curPoint->x;
  1157.         curPoint->x = (float) x;
  1158.         curPoint->tg.x0 += (float) dx;
  1159.         curPoint->tg.x1 += (float) dx;
  1160.     }
  1161.     dy = (float)y - curPoint->y;
  1162.     curPoint->y = (float)y;
  1163.     curPoint->tg.y0 += (float) dy;
  1164.     curPoint->tg.y1 += (float) dy;
  1165.  
  1166.     return 1;
  1167. }
  1168.  
  1169. /*---------------------------------------------------------------------------*
  1170.  *            MoveTangente
  1171.  *---------------------------------------------------------------------------*/
  1172. int
  1173. MoveTangente( int sens, int mousex, int mousey )
  1174. {
  1175.     float    x, y, dx, dy, slope;
  1176.     Tangente *tg;
  1177.  
  1178.     OrthoTransform( mousex, mousey, &x, &y );
  1179.  
  1180.     if ( sens == -1 )
  1181.     {
  1182.         x = INF(x, curPoint->x);
  1183.     }
  1184.     else
  1185.     {
  1186.         x = SUP(x, curPoint->x);
  1187.     }
  1188.     if ( x != curPoint->x )
  1189.     {
  1190.         slope =        (curPoint->y - y);
  1191.         slope /=    (curPoint->x - x);
  1192.         dx = 25. / fsqrt( slope*slope + 1. );
  1193.         dy = dx*slope;
  1194.     }
  1195.     else
  1196.     {
  1197.         dx = 0.;
  1198.         dy = (curPoint->y < y) ? sens*25. : -sens*25.;
  1199.     }
  1200.  
  1201.     dx *= LUTRATIO;
  1202.     dy *= LUTRATIO;
  1203.  
  1204.     tg = &curPoint->tg;
  1205.     tg->x0 = curPoint->x;
  1206.     tg->y0 = curPoint->y;
  1207.     if ( curPoint->last != NULL ) {
  1208.         tg->x0 -= dx;
  1209.         tg->y0 -= dy;
  1210.     }
  1211.     tg->x1 = curPoint->x;
  1212.     tg->y1 = curPoint->y;
  1213.     if ( curPoint->next != NULL )
  1214.     {
  1215.         tg->x1 += dx;
  1216.         tg->y1 += dy;
  1217.     }
  1218.  
  1219.     return 1;
  1220. }
  1221.  
  1222. /*---------------------------------------------------------------------------*
  1223.  *            GetPolynome
  1224.  *---------------------------------------------------------------------------*/
  1225. /*
  1226.     we want a polynom P(x) = Ax^3 + Bx^2 + Cx + D
  1227.     so that : P(a0) = b0, P'(a0) = t0, P(a1) = b1, P'(a1) = t1 
  1228.     i.e.
  1229.  
  1230.     | a0^3        a0^2    a0    1 | |A|      |b0|
  1231.     | a1^3        a1^2    a1    1 | |B| = |b1|
  1232.     | 3a0^2        2a0        1    0 | |C|      |t0|
  1233.     | 3a1^2        2a1        1    0 | |D|   |t1|
  1234. */
  1235. void
  1236. GetPolynome(
  1237.     int mode,
  1238.     float a0, float b0, float t0,
  1239.     float a1, float b1, float t1,
  1240.     float coeff[4] )
  1241. {
  1242.     Matrix    mat, INV_mat;
  1243.     int    i;
  1244.     float    val;
  1245.  
  1246.     switch (mode)
  1247.     {
  1248.         case CONSTANT:
  1249. /*            we want P(x) = b0 */
  1250.             coeff[0] = 0.;
  1251.             coeff[1] = 0.;
  1252.             coeff[2] = 0.;
  1253.             coeff[3] = b0;
  1254.             break;
  1255.  
  1256.         case LINEAR:
  1257. /*
  1258.             we want P(x) = b0 + (x-a0)/(a1-a0)*(b1-b0)
  1259.             i.e. P(x) = x*[(b1-b0)/(a1-a0)] + b0 - a0*[(b1-b0)/(a1-a0)]
  1260. */
  1261.             val = (b1-b0)/(a1-a0);
  1262.             coeff[0] = 0.;
  1263.             coeff[1] = 0.;
  1264.             coeff[2] = val;
  1265.             coeff[3] = b0 - a0*val;
  1266.             break;
  1267.  
  1268.         case POLYNOMIAL:
  1269. /*
  1270.             we want a polynom P(x) = Ax^3 + Bx^2 + Cx + D
  1271.             so that : P(a0) = b0, P'(a0) = t0, P(a1) = b1, P'(a1) = t1 
  1272.             i.e.
  1273.         
  1274.             | a0^3        a0^2    a0    1 | |A|      |b0|
  1275.             | a1^3        a1^2    a1    1 | |B| = |b1|
  1276.             | 3a0^2        2a0        1    0 | |C|      |t0|
  1277.             | 3a1^2        2a1        1    0 | |D|   |t1|
  1278. */
  1279.             val = 1.;
  1280.             for (i=3; i>=0; i--)
  1281.             {
  1282.                 mat[0][i] = val;
  1283.                 val *= a0;
  1284.             }
  1285.         
  1286.             val = 1.;
  1287.             for (i=3; i>=0; i--)
  1288.             {
  1289.                 mat[1][i] = val;
  1290.                 val *= a1;
  1291.             }
  1292.         
  1293.             mat[2][3] = 0.;
  1294.             mat[2][2] = 1.;
  1295.             mat[2][1] = 2.*a0;
  1296.             mat[2][0] = 3.*a0*a0;
  1297.         
  1298.             mat[3][3] = 0.;
  1299.             mat[3][2] = 1.;
  1300.             mat[3][1] = 2.*a1;
  1301.             mat[3][0] = 3.*a1*a1;
  1302.         
  1303.             invertmat( mat, INV_mat );
  1304.         
  1305.             for (i=0; i<4; i++)
  1306.                 coeff[i] = INV_mat[i][0]*b0 +
  1307.                     INV_mat[i][1]*b1 +
  1308.                     INV_mat[i][2]*t0 +
  1309.                     INV_mat[i][3]*t1;
  1310.             break;
  1311.     }
  1312. }
  1313.  
  1314. /*---------------------------------------------------------------------------*
  1315.  *            OrthoTransform
  1316.  *---------------------------------------------------------------------------*/
  1317. void
  1318. OrthoTransform( int mx, int my, float *x, float *y )
  1319. {
  1320.  float    xf, yf;
  1321.  
  1322.  xf =    (float) mx;
  1323.  xf /=    (float) W;
  1324.  xf *=    (float) (RIGHT - LEFT);
  1325.  xf +=    (float) LEFT;
  1326.  
  1327.  yf =    (float) my;
  1328.  yf /=    (float) H;
  1329.  yf *=    (float) (TOP - BOTTOM);
  1330.  yf +=    (float) BOTTOM;
  1331.  
  1332.  *x = xf;
  1333.  *y = yf;
  1334. }
  1335.  
  1336. /*---------------------------------------------------------------------------*
  1337.  *            Polynome4
  1338.  *---------------------------------------------------------------------------*/
  1339. float
  1340. Polynome4( float x, float *coeff )
  1341. {
  1342.  int    j;
  1343.  float    val = coeff[0];
  1344.  
  1345.  for (j=1; j<4; j++) {
  1346.     val *= x;
  1347.     val += coeff[j];
  1348.  }
  1349.  
  1350.  return    val;
  1351. }
  1352.  
  1353. /*---------------------------------------------------------------------------*
  1354.  *            MAIN
  1355.  *---------------------------------------------------------------------------*/
  1356. #ifdef    YACME_DBG
  1357. #include "RGBA.h"
  1358. int
  1359. main( int argc, char *argv[] )
  1360. {
  1361.     glutInit( &argc, argv );
  1362.  
  1363.     YACME_init(
  1364.         0, 0, WINWIDTH, WINHEIGHT,
  1365.         256, (float**)RGBA,
  1366.         NULL, NULL
  1367.     );
  1368.     glutMainLoop();
  1369.     return 0;             /* ANSI C requires main to return int. */
  1370. }
  1371. #endif
  1372.  
  1373.